/*
 * Grafo.h
 *
 *  Created on: 30/ott/2013
 *      Author: angelo
 */

#ifndef GRAFO_H_
#define GRAFO_H_

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <list>
#include <vector>
#include <map>
#include <omp.h>

#include "Node.h"
#include "Config.h"
#include "StemIslands.h"
#include "SteinerNode.h"

#ifndef M_SQRT3
#define M_SQRT3		1.7320508075688772935	/* sqrt(3) */
#endif

class Grafo {
public:
	Grafo();
	Grafo(Node *n);
	virtual ~Grafo();

	void createFromStemIslands(StemIslands *si);

	void add3SteinerPoints(void);

	Grafo *MVCseekerParallel(double radius, int budget, int nthreadsActive);
	Grafo *MVCseeker(double radius, int budget);

	Grafo *insertStemNodeOnEdge(double nOfRadios, double radius);
	Grafo *insertStemNodeOnEdgeOk(double nOfRadios, double radius);
	Grafo *insertStemNodeOnEdgeFinal(double nOfRadios, double radius);

	// calculate the cost of the graph (as the number of vertex)
	int cost(void);

	// calculate the number of stem-nodes necessary to buinld the tree
	int getStemCost(void) const;
	void setStemCost(int stemCost);

	int getStemWidth(void) const;
	void setStemWidth(int stemWidth);

	int getDistanceCost(void) const;
	void setDistanceCost(int distanceCost);

	double getDistanceStemStepCost() const;
	void setDistanceStemStepCost(double distanceStemStepCost);

	void reactivateAllNodes(int thr_idx);

	Grafo *cloneGraph(void);

	void clearAll(void);

private:

	void findBestTree(list<Grafo *> &boundary, int budget, double radius, Grafo *prevNode,
			Grafo * &local, Grafo * &global, int actualTreeCost, double actualTreeDistanceCost,
			int actualTreeWidth, double actualTreeDistanceStemStepCost, int thr_idx);

	int calculateWidth(Grafo *prevNode, Grafo *actualNode);
	int calculateCost(Grafo *prevNode, Grafo *actualNode, double radius, double &distanceStemsCost);
	int calculateCostOld(Grafo *prevNode, Grafo *actualNode, double radius);
	double calculateDistanceCost(Grafo *prevNode, Grafo *actualNode);
	bool checkActive(Grafo *prevNode, Grafo *actualNode, int thr_idx);
	bool checkLink(Grafo *prevNode, Grafo *actualNode);

	void addNode(Grafo *parentNode, Grafo *actualNode);
	void removeNode(Grafo *parentNode, Grafo *actualNode);

	void coutString(void);

public:
	Node *nodo;
	list<Grafo *> figli;

	// creo una lista circolare
	Grafo *nextGraph;
	Grafo *previousGraph;

	bool activeMVC[MAX_PARALLEL_THREADS];

	int nStemNodes;

private:
	int stemCost;
	int stemWidth;
	double distanceCost;
	double distanceStemStepCost;
};

#endif /* GRAFO_H_ */
